const ChatSession = require('../models/ChatSession')
const ChatMessage = require('../models/ChatMessage')
const axios = require('axios')
const logger = require('../utils/logger')
const { generateUUID } = require('../utils/crypto')
const { ERROR_CODES, MESSAGE_ROLES } = require('../utils/constants')
const { AppError, NotFoundError, ValidationError } = require('../middleware/errorHandler')

class ChatService {
  /**
   * 创建新的聊天会话
   */
  static async createSession(userId, sessionData) {
    try {
      const { title, systemPrompt, aiConfigId, tags = [] } = sessionData
      
      const session = await ChatSession.create({
        id: generateUUID(),
        userId,
        title: title || '新对话',
        systemPrompt: systemPrompt || '',
        aiConfigId,
        tags,
        messageCount: 0,
        lastMessageAt: null,
        isPinned: false,
        isActive: true,
        metadata: {
          totalTokens: 0,
          totalCost: 0,
          createdFrom: 'web'
        }
      })
      
      logger.info('Chat session created', {
        userId,
        sessionId: session.id,
        title: session.title
      })
      
      return session
    } catch (error) {
      logger.error('Failed to create chat session', {
        error: error.message,
        userId,
        sessionData
      })
      throw error
    }
  }
  
  /**
   * 获取用户的聊天会话列表
   */
  static async getUserSessions(userId, options = {}) {
    try {
      const {
        page = 1,
        limit = 20,
        search,
        tags,
        isPinned,
        isActive = true,
        sortBy = 'updatedAt',
        sortOrder = 'desc'
      } = options
      
      const { Op } = require('sequelize')
      let where = { userId }
      
      if (isActive !== undefined) {
        where.isActive = isActive
      }
      
      if (isPinned !== undefined) {
        where.isPinned = isPinned
      }
      
      if (search) {
        where[Op.or] = [
          { title: { [Op.like]: `%${search}%` } },
          { systemPrompt: { [Op.like]: `%${search}%` } }
        ]
      }
      
      if (tags && tags.length > 0) {
        where.tags = { [Op.contains]: tags }
      }
      
      const offset = (page - 1) * limit
      const order = [[sortBy, sortOrder.toUpperCase()]]
      
      const { count, rows } = await ChatSession.findAndCountAll({
        where,
        limit,
        offset,
        order
      })
      
      return {
        data: rows,
        pagination: {
          page,
          limit,
          total: count,
          pages: Math.ceil(count / limit)
        }
      }
    } catch (error) {
      logger.error('Failed to get user sessions', {
        error: error.message,
        userId,
        options
      })
      throw error
    }
  }
  
  /**
   * 获取聊天会话详情
   */
  static async getSession(userId, sessionId) {
    try {
      const session = await ChatSession.findByPk(sessionId)
      
      if (!session) {
        throw new NotFoundError('聊天会话', sessionId)
      }
      
      // 检查会话所有权
      if (session.userId !== userId) {
        throw new AppError(ERROR_CODES.ACCESS_DENIED, '无权访问此聊天会话')
      }
      
      return session
    } catch (error) {
      logger.error('Failed to get session', {
        error: error.message,
        userId,
        sessionId
      })
      throw error
    }
  }
  
  /**
   * 更新聊天会话
   */
  static async updateSession(userId, sessionId, updateData) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      const allowedFields = ['title', 'systemPrompt', 'aiConfigId', 'tags', 'isPinned']
      const filteredData = {}
      
      for (const field of allowedFields) {
        if (updateData.hasOwnProperty(field)) {
          filteredData[field] = updateData[field]
        }
      }
      
      const [updatedRowsCount] = await ChatSession.update(filteredData, {
        where: { id: sessionId }
      })
      
      if (updatedRowsCount === 0) {
        throw new NotFoundError('聊天会话', sessionId)
      }
      
      const updatedSession = await ChatSession.findByPk(sessionId)
      
      logger.info('Chat session updated', {
        userId,
        sessionId,
        updatedFields: Object.keys(filteredData)
      })
      
      return updatedSession
    } catch (error) {
      logger.error('Failed to update session', {
        error: error.message,
        userId,
        sessionId,
        updateData
      })
      throw error
    }
  }
  
  /**
   * 删除聊天会话
   */
  static async deleteSession(userId, sessionId, permanent = false) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      if (permanent) {
        // 永久删除会话和所有消息
        await ChatMessage.destroy({ where: { sessionId } })
        await ChatSession.destroy({ where: { id: sessionId } })
        
        logger.info('Chat session permanently deleted', {
          userId,
          sessionId
        })
      } else {
        // 软删除
        await ChatSession.update({ isActive: false }, {
          where: { id: sessionId }
        })
        
        logger.info('Chat session soft deleted', {
          userId,
          sessionId
        })
      }
      
      return { success: true }
    } catch (error) {
      logger.error('Failed to delete session', {
        error: error.message,
        userId,
        sessionId,
        permanent
      })
      throw error
    }
  }
  
  /**
   * 恢复已删除的会话
   */
  static async restoreSession(userId, sessionId) {
    try {
      const session = await ChatSession.findByPk(sessionId)
      
      if (!session) {
        throw new NotFoundError('聊天会话', sessionId)
      }
      
      if (session.userId !== userId) {
        throw new AppError(ERROR_CODES.ACCESS_DENIED, '无权访问此聊天会话')
      }
      
      if (session.isActive) {
        throw new ValidationError('会话未被删除，无需恢复')
      }
      
      await ChatSession.update({ isActive: true }, {
        where: { id: sessionId }
      })
      
      const restoredSession = await ChatSession.findByPk(sessionId)
      
      logger.info('Chat session restored', {
        userId,
        sessionId
      })
      
      return restoredSession
    } catch (error) {
      logger.error('Failed to restore session', {
        error: error.message,
        userId,
        sessionId
      })
      throw error
    }
  }
  
  /**
   * 发送消息
   */
  static async sendMessage(userId, sessionId, messageData) {
    try {
      // 检查会话是否存在且用户有权限
      const session = await this.getSession(userId, sessionId)
      
      if (!session.isActive) {
        throw new ValidationError('无法向已删除的会话发送消息')
      }
      
      // 获取AI配置
      let aiConfig
      if (messageData.aiConfigId) {
        // 如果提供了aiConfigId，从数据库获取配置
        const AiConfig = require('../models/AiConfig')
        aiConfig = await AiConfig.findByPk(messageData.aiConfigId)
        if (!aiConfig) {
          throw new ValidationError('指定的AI配置不存在')
        }
      } else if (session.aiConfigId) {
        // 使用会话的默认AI配置
        const AiConfig = require('../models/AiConfig')
        aiConfig = await AiConfig.findByPk(session.aiConfigId)
        if (!aiConfig) {
          throw new ValidationError('会话的AI配置不存在')
        }
      } else {
        throw new ValidationError('未指定AI配置')
      }
      
      if (!aiConfig.apiKey) {
        throw new ValidationError('AI配置缺少API密钥')
      }

      // 构建消息历史
      const messages = []
      if (session.systemPrompt) {
        messages.push({ role: 'system', content: session.systemPrompt })
      }
      messages.push({ role: 'user', content: messageData.content })

      // 调用AI API
      const aiResponse = await axios.post('http://localhost:806/api/ai/chat', {
        model: aiConfig.model || 'deepseek-chat',
        temperature: aiConfig.temperature || 0.7,
        max_tokens: aiConfig.maxTokens || 8000,
        apiKey: aiConfig.apiKey,
        apiUrl: aiConfig.baseUrl,
        messages: messages
      })

      if (!aiResponse.data.success) {
        throw new Error(aiResponse.data.message || 'AI API调用失败')
      }

      const assistantContent = aiResponse.data.data.message
      const usage = aiResponse.data.data.usage

      // 保存用户消息
      const userMessage = await ChatMessage.create({
        id: generateUUID(),
        sessionId,
        userId,
        role: MESSAGE_ROLES.USER,
        content: messageData.content,
        aiConfigId: messageData.aiConfigId || session.aiConfigId,
        metadata: {
          aiConfigId: messageData.aiConfigId || session.aiConfigId,
          timestamp: new Date().toISOString()
        }
      })

      // 保存AI回复
      const assistantMessage = await ChatMessage.create({
        id: generateUUID(),
        sessionId,
        userId,
        role: MESSAGE_ROLES.ASSISTANT,
        content: assistantContent,
        aiConfigId: messageData.aiConfigId || session.aiConfigId,
        metadata: {
          aiConfigId: messageData.aiConfigId || session.aiConfigId,
          model: aiConfig.model,
          provider: aiConfig.provider,
          tokenUsage: usage,
          timestamp: new Date().toISOString()
        }
      })

      const result = {
        userMessage,
        assistantMessage,
        tokenUsage: usage,
        responseTime: 0
      }
      
      // 更新会话统计信息
      await this.updateSessionStats(sessionId, result.tokenUsage, result.responseTime)
      
      // 如果是第一条消息且会话标题是默认的，自动生成标题
      if (session.messageCount === 0 && session.title === '新对话') {
        const autoTitle = this.generateAutoTitle(messageData.content)
        await ChatSession.update({ title: autoTitle }, { where: { id: sessionId } })
      }
      
      logger.info('Message sent successfully', {
        userId,
        sessionId,
        messageLength: messageData.content.length,
        responseTime: result.responseTime
      })
      
      return {
        userMessage: result.userMessage,
        assistantMessage: result.assistantMessage,
        session: await ChatSession.findByPk(sessionId)
      }
    } catch (error) {
      logger.error('Failed to send message', {
        error: error.message,
        stack: error.stack,
        userId,
        sessionId,
        messageData
      })
      console.error('ChatService.sendMessage error:', error)
      throw error
    }
  }
  
  /**
   * 获取会话消息列表
   */
  static async getSessionMessages(userId, sessionId, options = {}) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      const {
        page = 1,
        limit = 50,
        role,
        search,
        sortBy = 'createdAt',
        sortOrder = 'asc'
      } = options
      
      const { Op } = require('sequelize')
      let where = { sessionId, isDeleted: false }
      
      if (role) {
        where.role = role
      }
      
      if (search) {
        where.content = { [Op.like]: `%${search}%` }
      }
      
      const offset = (page - 1) * limit
      const order = [[sortBy, sortOrder.toUpperCase()]]
      
      const { count, rows } = await ChatMessage.findAndCountAll({
        where,
        limit,
        offset,
        order
      })
      
      const messages = {
        data: rows,
        pagination: {
          page,
          limit,
          total: count,
          pages: Math.ceil(count / limit)
        }
      }
      
      return messages
    } catch (error) {
      logger.error('Failed to get session messages', {
        error: error.message,
        userId,
        sessionId,
        options
      })
      throw error
    }
  }
  
  /**
   * 编辑消息
   */
  static async editMessage(userId, sessionId, messageId, newContent) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      // 获取消息
      const message = await ChatMessage.findByPk(messageId)
      if (!message) {
        throw new NotFoundError('消息', messageId)
      }
      
      if (message.sessionId !== sessionId) {
        throw new ValidationError('消息不属于指定会话')
      }
      
      // 只允许编辑用户消息
      if (message.role !== MESSAGE_ROLES.USER) {
        throw new ValidationError('只能编辑用户消息')
      }
      
      // 保存编辑历史
      const editHistory = message.editHistory || []
      editHistory.push({
        content: message.content,
        editedAt: new Date().toISOString()
      })
      
      await ChatMessage.update({
        content: newContent,
        isEdited: true,
        editHistory
      }, {
        where: { id: messageId }
      })
      
      const editedMessage = await ChatMessage.findByPk(messageId)
      
      logger.info('Message edited', {
        userId,
        sessionId,
        messageId,
        originalLength: message.content.length,
        newLength: newContent.length
      })
      
      return editedMessage
    } catch (error) {
      logger.error('Failed to edit message', {
        error: error.message,
        userId,
        sessionId,
        messageId
      })
      throw error
    }
  }
  
  /**
   * 删除消息
   */
  static async deleteMessage(userId, sessionId, messageId, permanent = false) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      // 获取消息
      const message = await ChatMessage.findByPk(messageId)
      if (!message) {
        throw new NotFoundError('消息', messageId)
      }
      
      if (message.sessionId !== sessionId) {
        throw new ValidationError('消息不属于指定会话')
      }
      
      if (permanent) {
        await ChatMessage.destroy({ where: { id: messageId } })
      } else {
        await ChatMessage.update({ isDeleted: true }, {
          where: { id: messageId }
        })
      }
      
      // 更新会话消息计数
      const session = await ChatSession.findByPk(sessionId)
      if (session) {
        await ChatSession.update({
          messageCount: Math.max(0, session.messageCount - 1)
        }, {
          where: { id: sessionId }
        })
      }
      
      logger.info('Message deleted', {
        userId,
        sessionId,
        messageId,
        permanent
      })
      
      return { success: true }
    } catch (error) {
      logger.error('Failed to delete message', {
        error: error.message,
        userId,
        sessionId,
        messageId,
        permanent
      })
      throw error
    }
  }
  
  /**
   * 添加消息反应
   */
  static async addMessageReaction(userId, sessionId, messageId, reaction) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      const message = await ChatMessage.findByPk(messageId)
      if (!message) {
        throw new NotFoundError('消息', messageId)
      }
      
      if (message.sessionId !== sessionId) {
        throw new ValidationError('消息不属于指定会话')
      }
      
      const reactions = message.reactions || []
      const existingReactionIndex = reactions.findIndex(r => r.userId === userId)
      
      if (existingReactionIndex >= 0) {
        reactions[existingReactionIndex] = {
          userId,
          type: reaction,
          createdAt: new Date().toISOString()
        }
      } else {
        reactions.push({
          userId,
          type: reaction,
          createdAt: new Date().toISOString()
        })
      }
      
      await ChatMessage.update({ reactions }, {
        where: { id: messageId }
      })
      
      const updatedMessage = await ChatMessage.findByPk(messageId)
      
      logger.info('Message reaction added', {
        userId,
        sessionId,
        messageId,
        reaction
      })
      
      return updatedMessage
    } catch (error) {
      logger.error('Failed to add message reaction', {
        error: error.message,
        userId,
        sessionId,
        messageId,
        reaction
      })
      throw error
    }
  }
  
  /**
   * 移除消息反应
   */
  static async removeMessageReaction(userId, sessionId, messageId, reaction) {
    try {
      // 检查会话是否存在且用户有权限
      await this.getSession(userId, sessionId)
      
      const message = await ChatMessage.findByPk(messageId)
      if (!message) {
        throw new NotFoundError('消息', messageId)
      }
      
      if (message.sessionId !== sessionId) {
        throw new ValidationError('消息不属于指定会话')
      }
      
      const reactions = (message.reactions || []).filter(r => r.userId !== userId)
      
      await ChatMessage.update({ reactions }, {
        where: { id: messageId }
      })
      
      const updatedMessage = await ChatMessage.findByPk(messageId)
      
      logger.info('Message reaction removed', {
        userId,
        sessionId,
        messageId,
        reaction
      })
      
      return updatedMessage
    } catch (error) {
      logger.error('Failed to remove message reaction', {
        error: error.message,
        userId,
        sessionId,
        messageId,
        reaction
      })
      throw error
    }
  }
  
  /**
   * 搜索消息
   */
  static async searchMessages(userId, query, options = {}) {
    try {
      const {
        sessionId,
        page = 1,
        limit = 20,
        role,
        dateFrom,
        dateTo
      } = options
      
      // 如果指定了sessionId，检查权限
      if (sessionId) {
        await this.getSession(userId, sessionId)
      }
      
      const { Op } = require('sequelize')
      
      const whereClause = {
        userId,
        isDeleted: false,
        content: {
          [Op.like]: `%${query}%`
        }
      }
      
      if (sessionId) {
        whereClause.sessionId = sessionId
      }
      
      if (role) {
        whereClause.role = role
      }
      
      if (dateFrom || dateTo) {
        whereClause.createdAt = {}
        if (dateFrom) {
          whereClause.createdAt[Op.gte] = new Date(dateFrom)
        }
        if (dateTo) {
          whereClause.createdAt[Op.lte] = new Date(dateTo)
        }
      }
      
      const offset = (page - 1) * limit
      
      const results = await ChatMessage.findAndCountAll({
        where: whereClause,
        limit,
        offset,
        order: [['createdAt', 'DESC']]
      })
      
      const searchResults = {
        data: results.rows,
        total: results.count,
        page,
        limit,
        totalPages: Math.ceil(results.count / limit)
      }
      
      return searchResults
    } catch (error) {
      logger.error('Failed to search messages', {
        error: error.message,
        userId,
        query,
        options
      })
      throw error
    }
  }
  
  /**
   * 导出会话
   */
  static async exportSession(userId, sessionId, format = 'json') {
    try {
      // 检查会话是否存在且用户有权限
      const session = await this.getSession(userId, sessionId)
      
      // 获取所有消息
      const messages = await ChatMessage.findAndCountAll({
        where: {
          sessionId,
          isDeleted: false
        },
        limit: 1000,
        order: [['createdAt', 'ASC']]
      })
      
      const exportData = {
        session: {
          id: session.id,
          title: session.title,
          systemPrompt: session.systemPrompt,
          tags: session.tags,
          createdAt: session.createdAt,
          updatedAt: session.updatedAt
        },
        messages: messages.rows.map(msg => ({
          role: msg.role,
          content: msg.content,
          createdAt: msg.createdAt,
          metadata: msg.metadata
        })),
        exportedAt: new Date().toISOString(),
        exportedBy: userId
      }
      
      if (format === 'text') {
        return this.formatAsText(exportData)
      }
      
      return exportData
    } catch (error) {
      logger.error('Failed to export session', {
        error: error.message,
        userId,
        sessionId,
        format
      })
      throw error
    }
  }
  
  /**
   * 更新会话统计信息
   */
  static async updateSessionStats(sessionId, tokenUsage, responseTime) {
    try {
      const session = await ChatSession.findByPk(sessionId)
      if (!session) return
      
      // 简化成本计算，暂时设为0
      const cost = 0
      
      await ChatSession.update({
        messageCount: session.messageCount + 2, // 用户消息 + AI回复
        lastMessageAt: new Date().toISOString()
      }, {
        where: { id: sessionId }
      })
    } catch (error) {
      logger.error('Failed to update session stats', {
        error: error.message,
        sessionId,
        tokenUsage,
        responseTime
      })
    }
  }
  
  /**
   * 生成自动标题
   */
  static generateAutoTitle(content) {
    // 简单的标题生成逻辑
    const maxLength = 30
    let title = content.trim()
    
    // 移除换行符
    title = title.replace(/\n/g, ' ')
    
    // 截断长度
    if (title.length > maxLength) {
      title = title.substring(0, maxLength) + '...'
    }
    
    return title || '新对话'
  }
  
  /**
   * 格式化为文本
   */
  static formatAsText(exportData) {
    let text = `会话标题: ${exportData.session.title}\n`
    text += `创建时间: ${exportData.session.createdAt}\n`
    text += `系统提示: ${exportData.session.systemPrompt || '无'}\n`
    text += `标签: ${exportData.session.tags.join(', ') || '无'}\n\n`
    text += '='.repeat(50) + '\n\n'
    
    for (const message of exportData.messages) {
      const role = message.role === MESSAGE_ROLES.USER ? '用户' : 
                   message.role === MESSAGE_ROLES.ASSISTANT ? 'AI助手' : '系统'
      text += `${role}: ${message.content}\n\n`
    }
    
    text += '='.repeat(50) + '\n'
    text += `导出时间: ${exportData.exportedAt}\n`
    
    return text
  }
}

module.exports = ChatService